using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.CodeDom;
using System.Configuration;
using System.CodeDom.Compiler;
using System.Threading;

namespace AppSettingsGenerator.Targets
{
	public class Generator : CommonGenerator.CommonGenerator
	{
		public Generator()
		{
		}

		public override void WriteClass(TextWriter writer)
		{
			var config = this.ConfigurationObject;

			var ns = CreateCodeNamespace();
			var type = ns.Types[0];
			var appSettings = new CodeTypeDeclaration("AppSettings");
			type.Members.Add(appSettings);
			appSettings.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;


			var connectionStrings = new CodeTypeDeclaration("ConnectionStrings");
			type.Members.Add(connectionStrings);
			connectionStrings.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;

			type.Attributes = MemberAttributes.Abstract;

			foreach(KeyValueConfigurationElement setting in config.AppSettings.Settings)
			{
				CodeMemberProperty property = new CodeMemberProperty();
				property.HasSet = false;
				property.HasGet = true;
				property.Attributes = MemberAttributes.Static | MemberAttributes.Public;
				property.Type = new CodeTypeReference(typeof(String));
				property.Name = Normalize(setting.Key);
				var getSettingCall =
					new CodeIndexerExpression(
						new CodePropertyReferenceExpression(
							new CodeTypeReferenceExpression(typeof(ConfigurationManager)),
							"AppSettings"),
						new CodePrimitiveExpression(setting.Key));
				property.GetStatements.Add(new CodeMethodReturnStatement(getSettingCall));
				appSettings.Members.Add(property);
			}

			foreach(ConnectionStringSettings connectionString in config.ConnectionStrings.ConnectionStrings)
			{
				CodeMemberProperty property = new CodeMemberProperty();
				property.HasSet = false;
				property.HasGet = true;
				property.Attributes = MemberAttributes.Static | MemberAttributes.Public;
				property.Type = new CodeTypeReference(typeof(ConnectionStringSettings));
				property.Name = Normalize(connectionString.Name);

				var getSettingCall =
					new CodeIndexerExpression(
						new CodePropertyReferenceExpression(
							new CodeTypeReferenceExpression(typeof(ConfigurationManager)),
							"ConnectionStrings"),
						new CodePrimitiveExpression(connectionString.Name));
				property.GetStatements.Add(new CodeMethodReturnStatement(getSettingCall));
				connectionStrings.Members.Add(property);
			}

			var provider = CreateProvider();
			provider.GenerateCodeFromNamespace(ns, writer, new CodeGeneratorOptions());
		}

		private string Normalize(string name)
		{
			var textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
			var splittedNameInPascal = name.Split(' ')
				.Select(split => split.ToCharArray())
				.Select((array, i) =>
				{
					if(i != 0)
						array[0] = textInfo.ToUpper(array[0]);
					return array;
				})
				.Select(array => new String(array));
			return String.Join(String.Empty, splittedNameInPascal.ToArray());
		}


	}

}
